<template>
  <div class="listview">
    <scroll :data="data" class="listview-scroll" ref="listviewscroll" :listenScroll="listenScroll" :probeType="probeType" @scroll="scroll">
      <!-- 歌手列表 -->
      <ul>
        <li class="list-group" v-for="(item, index) in data" :key="index" ref="listGroup">
          <h2 class="list-group-title" v-html="item.title"></h2>
          <ul>
            <li class="list-group-item" v-for="(item, index) in item.items" :key="index" :data-id="item.id" @click="selectItem(item)">
              <img v-lazy="item.avatar" alt="" class="avatar" width="50" height="50">
              <span class="name" v-html="item.name"></span>
            </li>
          </ul>
        </li>
      </ul>
      <!-- 右侧字母列表 -->
      <!-- stop 阻止事件继续传播 -->
      <!-- prevent 阻止默认事件 -->
      <div class="list-shortcut" @touchstart="onShortcutTouchStart" @touchmove.stop.prevent="onShortcutTouchMove">
        <ul>
          <li v-for="(item, index) in shortcutList" :key="index" class="item" :data-index="index" :class="{'current' : currentIndex === index}">{{item}}</li>
        </ul>
      </div>

      <!-- 顶部title -->
      <div class="list-fixed" ref="fixed" v-show="fixedTitle">
        <div class="fixed-title">{{fixedTitle}}</div>
      </div>
    </scroll>
  </div>
</template>

<script type="text/ecmascript-6">
import Scroll from 'base/scroll/scroll'
import { getData, prefixStyle } from 'common/js/dom'
import { clearTimeout } from 'timers'
// 定义高度 字体高度 + padding值
const ANCHOR_HEIGHT = 18
// 定义顶部title高度
const TITLE_HEIGHT = 30
const transform = prefixStyle('transform')
export default{
  props: {
    data: {
      type: Array,
      default: () => []
    }
  },
  data () {
    return {
      scrollY: -1, // 默认-1 观测右侧实时滚动位置 也就是 listGroup 的高度 滚动了几个
      currentIndex: 0, // 当前高亮index
      diff: -1 // 滚动差用于顶部title向上顶效果
    }
  },
  /**
   * 在Vue中无论是 data / props / computed 都会被添加 get 和 set 去观测数据变化
   * 主要是为了和 DOM 做数据绑定
   */
  created () {
    /**
     * 我们之所以在 created 定义对象是因为我们并不需要观测 touch变化
     * 只是为了用于函数之间能够共享数据
     */
    // 坐标
    this.touch = {}
    this.listenScroll = true// 派发滚动事件
    this.listHeight = []// listGroup 高度数组
    this.probeType = 3
  },
  computed: {
    shortcutList () {
      return this.data.map((item, index) => {
        return item.title.substring(0, 1)
      })
    },
    fixedTitle () {
      // 下拉到极限就不显示title
      if (this.scrollY > 0) {
        return ''
      }
      return this.data[this.currentIndex] ? this.data[this.currentIndex].title : ''
    }
  },
  methods: {
    onShortcutTouchStart (event) {
      // console.log(event)
      // 获取自定义属性
      let anchorIndex = getData(event.target, 'index')
      // 获取坐标对象
      let firstTouch = event.touches[0]
      // 手指触碰屏幕一刻 记录Y轴坐标
      this.touch.y1 = firstTouch.pageY
      // 记录手指触碰屏幕一刻的 index
      this.touch.anchorIndex = anchorIndex
      this._scrollTo(anchorIndex)
    },

    onShortcutTouchMove (event) {
      // 获取坐标对象
      let firstTouch = event.touches[0]
      // 手指在屏幕上滑动记录在Y轴移动距离的坐标
      this.touch.y2 = firstTouch.pageY
      // 向下取整Math.floor 也可以写 | 0 移动的距离除以高度 = 移动了多少个标签
      let delta = (this.touch.y2 - this.touch.y1) / ANCHOR_HEIGHT | 0
      // 刚开始点击的index + 移动的多少个(delta)就可以得到手指移动到那个index
      let anchorIndex = parseInt(this.touch.anchorIndex) + delta
      this._scrollTo(anchorIndex)
    },
    // 滚动实时派发滚动事件
    scroll (pos) {
      // console.log(pos)
      this.scrollY = pos.y
    },
    _scrollTo (index) {
      // 处理用户点击右侧顶部问题
      if (!index && index !== 0) {
        return false
      }

      // 处理用户一直拖动到顶部与底部问题
      if (index < 0) {
        index = 0
      } else if (index > this.listHeight.length - 2) {
        index = this.listHeight.length - 2
      }

      // 需要给scrollY一个新值来显示高亮 当前点击的第几个index
      this.scrollY = -this.listHeight[index]
      this.$refs.listviewscroll.scrollToElement(this.$refs.listGroup[index], 0)
    },
    // 计算高度方法
    _calculateHeight () {
      // 每次都清空数组
      this.listHeight = []
      // 每个歌手分组的高度
      const list = this.$refs.listGroup
      // 开始的高度为0  当我们要看到第一个,那么距离顶部的距离就是0
      let height = 0
      this.listHeight.push(height)
      for (let i = 0; i < list.length; i++) {
        height += list[i].clientHeight
        // 把每一个元素依次添加进数组 第一个高度为 30 第二个高度为 50 那么第二个就是80
        this.listHeight.push(height)
      };
    },
    // 用户点击歌手
    selectItem (item) {
      this.$emit('select', item)
    },
    refresh () {
      this.$refs.listviewscroll.refresh()
    }
  },
  watch: {
    data () {
      // 数据变化到DOM变化有延迟 20
      clearTimeout(this.time)
      this.time = setTimeout(() => {
        this._calculateHeight()
      }, 20)
    },
    scrollY (newY) {
      // console.log(newY)

      // 滚动到顶部 newY > 0
      if (newY > 0) {
        this.currentIndex = 0
        return false
      }

      // 在中间部分滚动
      const listHeight = this.listHeight
      for (let i = 0; i < listHeight.length - 1; i++) {
        let height1 = listHeight[i]
        let height2 = listHeight[i + 1]
        if (-newY >= height1 && -newY < height2) {
          this.currentIndex = i
          // 一个区块的 listGroup 的极限减去滚动的距离 就是滚动差
          this.diff = height2 + newY
          return false
        }
      }

      // 当滚动到底部 而且 -newY 大于最后一个元素的上限
      this.currentIndex = listHeight.length - 2
    },

    diff (newVal) {
      // console.log(newVal)
      let fixedTop = (newVal > 0 && newVal < TITLE_HEIGHT) ? newVal - TITLE_HEIGHT : 0
      // console.log(fixedTop)
      if (this.fixedTop === fixedTop) {
        return false
      }
      this.fixedTop = fixedTop
      this.$refs.fixed.style[transform] = `translate3d(0, ${fixedTop}px, 0)`
    }
  },
  components: { Scroll }
}
</script>

<style lang="stylus" scoped rel="stylesheet/stylus">
  @import '~common/stylus/variable';
  .listview
    height 100%;
    width 100%;
    .listview-scroll
      height 100%;
      width 100%;
      overflow hidden;
      position relative;
      .list-group
        padding-bottom 20px;
        .list-group-title
          height 30px;
          line-height 30px;
          padding-left 20px;
          font-size $font-size-small;
          font-weight bold;
          background-color $color-highlight-background;
          color $color-text-l;
        .list-group-item
          display flex;
          align-items center;
          padding: 20px 0 0 30px;
          .avatar
            border-radius 50%;
            margin-right 20px;
          .name
            font-size: $font-size-medium;
            color: $color-text-l;
      .list-group:last-child
        padding-bottom 0;
      .list-shortcut
        position absolute;
        top 50%;
        right 0;
        transform translateY(-50%);
        width 20px;
        text-align center;
        background-color $color-background-d;
        padding 20px 0;
        border-radius 20px;
        z-index 100;
        .item
          font-size $font-size-small;
          padding 3px;
          color $color-text-l;
        .current
          color $color-theme;
      .list-fixed
        position absolute;
        top 0;
        left 0;
        right 0;
        .fixed-title
          height 30px;
          line-height 30px;
          background-color $color-highlight-background;
          font-size $font-size-small;
          font-weight bold;
          padding-left: 20px;
          color $color-text-l;
</style>
